﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Styx;
using Styx.CommonBot;
using Styx.CommonBot.Routines;
using Styx.Helpers;
using Styx.TreeSharp;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using Action = Styx.TreeSharp.Action;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Styx.Pathing;
using Styx.Common;
using System.Windows.Media;
using Styx.CommonBot.Frames;
using System.Diagnostics;

using U = Hunter.Helpers.Unit;
using CP = Hunter.CRSettings.CRSettings;
using L = Hunter.Helpers.Logs;
using T = Hunter.Helpers.targets;
using I = Hunter.Helpers.Interrupts;
using UI = Hunter.Helpers.UseItems;
using HKM = Hunter.Helpers.HotkeyManager;


namespace Hunter.Spells
{
    class SpellCasting
    {
        private static LocalPlayer Me { get { return StyxWoW.Me; } }
        public static int LastSpell { get; set; }

        #region spellid's
        public const int
            ARCANE_SHOT = 3044,
            BINDING_SHOT = 109248,
            WYVERN_STING = 19386,
            INTIMIDATION = 19577,
            EXHILARATION = 109304,
            IRON_HAWK = 109260,
            DIRE_BEAST = 120679,
            STAMPEDE = 109212,
            GLAIVE_TOSS = 117050,
            POWERSHOT = 109259,
            BARRAGE = 120360,
            FOCUSING_SHOT = 152245,
            BLACK_ARROW = 3674,
            CAMOUFLAGE = 51753,
            COBRA_SHOT = 77767,
            CONCUSSIVE_SHOT = 5116,
            COUNTER_SHOT = 147362,
            DETERRENCE = 148467,
            DISENGAGE = 781,
            DISTRACTING_SHOT = 20736,
            EXPLOSIVE_SHOT = 53301,
            EXPLOSIVE_TRAP = 13813,
            FEIGN_DEATH = 5384,
            FLARE = 1543,
            FREEZING_TRAP = 1499,
            ICE_TRAP = 13809,
            MASTERS_CALL = 53271,
            MEND_PET = 136,
            MISDIRECTION = 34477,
            MULTI_SHOT = 2643,
            TRANQUILIZING_SHOT = 19801,
            TRAP_LAUNCHER = 77769,
            LOCK_AND_LOAD = 168980,
            ALCHEMY_FLASK = 75525,
            SERPENT_STING = 118253,
            CRYSTAL_OF_INSANITY_BUFF = 127230,
            FLASK_OF_THE_EARTH_BUFF = 105694,
            FLASK_OF_THE_WARM_SUN_BUFF = 105691,
            FLASK_OF_WINTERS_BITE_BUFF = 105696,
            FLASK_OF_FALLING_LEAVES_BUFF = 105693,
            FLASK_OF_SPRING_BLOSSOMS_BUFF = 105689,
            CRYSTAL_OF_INSANITY_ITEM = 86569,
            FLASK_OF_THE_WARM_SUN = 76085,
            FLASK_OF_WINTERS_BITE = 76088,
            FLASK_OF_THE_EARTH = 76087,
            FLASK_OF_SPRING_BLOSSOMS = 76084,
            FLASK_OF_FALING_LEAVES = 76086,
            //BM
            KILL_COMMAND = 34026,
            BESTIAL_WRATH = 19574,
            FOCUS_FIRE = 82692,
            KILL_SHOT = 53351,
            //Racials
            WAR_STOMP = 20549,
            BLOOD_FURY = 20572,
            BERSERKING = 26297,
            GIFT_OF_THE_NAARU = 59544,
            FRENZY = 19615,
            MURDER_OF_CROWS = 131894;

        public const string
            TIME_WARP = "Time Warp",
            BLOODLUST = "Bloodlust",
            HEROISM = "Heroism",
            ANCIENT_HYSTERIA = "Ancient Hysteria",
            DRUMS_OF_RAGE = "Drums of Rage";
        #endregion


        public static bool NotHaveBloodLustAura
        {
            get
            {
                return !U.buffExists(BLOODLUST, Me)
                    && !U.buffExists(TIME_WARP, Me)
                    && !U.buffExists(HEROISM, Me)
                    && !U.buffExists(ANCIENT_HYSTERIA, Me)
                    && !U.buffExists(DRUMS_OF_RAGE, Me);
            }
        }

        #region timers
        public static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
        public static uint GetCurrentUnixTimestampMillis()
        {
            return (uint)(DateTime.UtcNow - UnixEpoch).TotalMilliseconds;
        }

        public static DateTime DateTimeFromUnixTimestampMillis(long millis)
        {
            return UnixEpoch.AddMilliseconds(millis);
        }
        
        #endregion




        #region cast  FocusFire
        public static Composite castFocusFire()
        {
            return
                new Decorator(ret => Me.GotTarget
                    && SpellManager.HasSpell(FOCUS_FIRE)
                    && (Me.HasAura("Frenzy")
                    && Me.GetAuraByName("Frenzy").StackCount >= 5)
                    && Me.CurrentTarget.Distance <= 39
                    && SpellManager.CanCast(FOCUS_FIRE)
                    && LastSpell != FOCUS_FIRE,
            new Action(ret =>
            {
                    SpellManager.Cast(FOCUS_FIRE);
                    L.combatLog(WoWSpell.FromId(FOCUS_FIRE).Name);
                    LastSpell = FOCUS_FIRE;
                
            }));
        }
        #endregion

        #region cast  Kill Shot
        public static Composite castKillShot()
        {
            return
                new Decorator(ret => SpellManager.HasSpell(KILL_SHOT)
                    && !U.spellOnCooldown(KILL_SHOT)
                    && Me.CurrentTarget.HealthPercent < 20
                    && Me.CurrentTarget.Distance <= 39
                    && LastSpell != KILL_SHOT
                    && SpellManager.CanCast(KILL_SHOT),
            new Action(ret =>
            {
                SpellManager.Cast(KILL_SHOT);
                L.combatLog(WoWSpell.FromId(KILL_SHOT).Name);
                LastSpell = KILL_SHOT;
            }));
        }
        #endregion


        #region cast  Bestial Wrath
        public static Composite castBestialWrath()
        {
            return
                new Decorator(ret => SpellManager.HasSpell(BESTIAL_WRATH)
                    && !U.spellOnCooldown(BESTIAL_WRATH)
                    && Me.CurrentTarget.Distance <= 39
                    && Me.Pet.IsWithinMeleeRangeOf(Me.CurrentTarget)
                    && U.targetExistence(Me.CurrentTarget) > 10
                    && SpellManager.CanCast(BESTIAL_WRATH)
                    && LastSpell != BESTIAL_WRATH,
            new Action(ret =>
            {
                SpellManager.Cast(BESTIAL_WRATH);
                L.combatLog(WoWSpell.FromId(BESTIAL_WRATH).Name);
                LastSpell = BESTIAL_WRATH;

            }));
        }
        #endregion

        #region cast kill command
        public static Composite castKillCommand()
        {
            return
                new Decorator(ret => Me.GotTarget
                    && SpellManager.HasSpell(KILL_COMMAND)
                    && Me.FocusPercent >= 40
                    && Me.CurrentTarget.Distance <= 39
                    && Me.Pet.IsWithinMeleeRangeOf(Me.CurrentTarget)
                    && SpellManager.CanCast(KILL_COMMAND)
                    && LastSpell != KILL_COMMAND,
            new Action(ret =>
            {
                SpellManager.Cast(KILL_COMMAND);
                L.combatLog(WoWSpell.FromId(KILL_COMMAND).Name);
                LastSpell = KILL_COMMAND;
            }));
        }
        #endregion


        #region cast multishot

        public static Composite castMultiShot()
        {
            return
                new Decorator(ret => Me.GotTarget
                    && SpellManager.HasSpell(MULTI_SHOT)
                    && Me.FocusPercent >= 40
                    && Me.CurrentTarget.Distance <= 39
                    && SpellManager.CanCast(MULTI_SHOT),
            new Action(ret =>
            {
                SpellManager.Cast(MULTI_SHOT);
                L.combatLog(WoWSpell.FromId(MULTI_SHOT).Name);
                LastSpell = MULTI_SHOT;

            }));
        }
        #endregion

        #region cast stampede

        public static Composite CastStampede()
        {
            return
                new Decorator(ret => Me.GotTarget
                    && useMyStampede
                    && SpellManager.HasSpell(STAMPEDE)
                    && !U.spellOnCooldown(STAMPEDE)
                    && Me.CurrentTarget.Distance >= 39
                    && SpellManager.CanCast(STAMPEDE)
                    && LastSpell != STAMPEDE,
            new Action(ret =>
            {
                SpellManager.Cast(STAMPEDE);
                L.combatLog(WoWSpell.FromId(STAMPEDE).Name);
                LastSpell = STAMPEDE;

            }));
        }
        #endregion

        #region naaru

        public static Composite CastNaruu()
        {
            return
                new Decorator(ret => Me.GotTarget
                    && SpellManager.HasSpell(GIFT_OF_THE_NAARU)
                    && !U.spellOnCooldown(GIFT_OF_THE_NAARU)
                    && Me.HealthPercent <= CP.myPrefs.PercentNaaru
                    && SpellManager.CanCast(GIFT_OF_THE_NAARU)
                    && LastSpell != GIFT_OF_THE_NAARU,
            new Action(ret =>
            {

                SpellManager.Cast(GIFT_OF_THE_NAARU);
                L.combatLog(WoWSpell.FromId(GIFT_OF_THE_NAARU).Name);
                LastSpell = GIFT_OF_THE_NAARU;

            }));
        }
        #endregion

        #region cast bloodfury

        public static Composite CastBloodfury()
        {
            return
                new Decorator(ret => Me.GotTarget
                    && SpellManager.HasSpell(BLOOD_FURY)
                    && !U.spellOnCooldown(BLOOD_FURY)
                    && SpellManager.CanCast(BLOOD_FURY)
                    && LastSpell != BLOOD_FURY,
            new Action(ret =>
            {
                SpellManager.Cast(BLOOD_FURY);
                L.combatLog(WoWSpell.FromId(BLOOD_FURY).Name);
                LastSpell = BLOOD_FURY;

            }));
        }
        #endregion

        #region cast berserking

        public static Composite CastBerserking()
        {
            return
                new Decorator(ret => Me.GotTarget
                    && SpellManager.HasSpell(BERSERKING)
                    && !U.spellOnCooldown(BERSERKING)
                    && NotHaveBloodLustAura
                    && SpellManager.CanCast(BERSERKING)
                    && LastSpell != BERSERKING,
            new Action(ret =>
            {
                SpellManager.Cast(BERSERKING);
                L.combatLog(WoWSpell.FromId(BERSERKING).Name);
                LastSpell = BERSERKING;

            }));
        }
        #endregion

        #region overlayed
        public static bool IsOverlayed(int spellID)
        {
            return Lua.GetReturnVal<bool>("return IsSpellOverlayed(" + spellID + ")", 0);
        }
        #endregion overlayed

        #region cast ice trap on me
        public static Composite CastIceTrapOnMe()
        {
            return
                new Decorator(ret => Me.GotTarget
                    && SpellManager.HasSpell(ICE_TRAP)
                    && U.buffExists(TRAP_LAUNCHER, Me)
                    && !U.spellOnCooldown(ICE_TRAP)
                    && SpellManager.CanCast(ICE_TRAP)
                    && LastSpell != ICE_TRAP,
            new Action(ret =>
            {
                SpellManager.Cast(ICE_TRAP);
                SpellManager.ClickRemoteLocation(Me.Location);
                L.combatLog(WoWSpell.FromId(ICE_TRAP).Name);
                LastSpell = ICE_TRAP;

            }));
        }
        #endregion

        #region cast ice trap
        public static Composite CastIceTrap()
        {
            return
                new Decorator(ret => Me.GotTarget
                    && SpellManager.HasSpell(ICE_TRAP)
                    && U.buffExists(TRAP_LAUNCHER, Me)
                    && !U.spellOnCooldown(ICE_TRAP)
                    && SpellManager.CanCast(ICE_TRAP)
                    && LastSpell != ICE_TRAP,
            new Action(ret =>
            {
                SpellManager.Cast(ICE_TRAP);
                SpellManager.ClickRemoteLocation(Me.CurrentTarget.Location);
                L.combatLog(WoWSpell.FromId(ICE_TRAP).Name);
                LastSpell = ICE_TRAP;

            }));
        }
        #endregion

        #region cast explosive trap
        public static Composite CastExplosiveTrap()
        {
            return
                new Decorator(ret => Me.GotTarget
                    && SpellManager.HasSpell(EXPLOSIVE_TRAP)
                    && U.buffExists(TRAP_LAUNCHER, Me)
                    && !U.spellOnCooldown(EXPLOSIVE_TRAP)
                    && SpellManager.CanCast(EXPLOSIVE_TRAP)
                    && LastSpell != EXPLOSIVE_TRAP,
            new Action(ret =>
            {
                SpellManager.Cast(EXPLOSIVE_TRAP);
                SpellManager.ClickRemoteLocation(Me.CurrentTarget.Location);
                L.combatLog(WoWSpell.FromId(EXPLOSIVE_TRAP).Name);
                LastSpell = EXPLOSIVE_TRAP;

            }));
        }
        #endregion

        #region cast traplauncher
        public static Composite CastTrapLauncher()
        {
            return
                new Decorator(ret => SpellManager.HasSpell(TRAP_LAUNCHER)
                    && !U.spellOnCooldown(TRAP_LAUNCHER)
                    && !U.buffExists(TRAP_LAUNCHER, Me)
                    && SpellManager.CanCast(TRAP_LAUNCHER)
                    && LastSpell != TRAP_LAUNCHER,
            new Action(ret =>
            {
                SpellManager.Cast(TRAP_LAUNCHER);
                L.combatLog(WoWSpell.FromId(TRAP_LAUNCHER).Name);
                LastSpell = TRAP_LAUNCHER;

            }));
        }
        #endregion

        #region cast exhilaration

        public static Composite CastExhilaration()
        {
            return
                new Decorator(ret => Me.GotTarget
                    && SpellManager.HasSpell(EXHILARATION)
                    && !U.spellOnCooldown(EXHILARATION)
                    && Me.HealthPercent <= CP.myPrefs.PercentExhilaration
                    && SpellManager.CanCast(EXHILARATION)
                    && LastSpell != EXHILARATION,
            new Action(ret =>
            {
                SpellManager.Cast(EXHILARATION);
                L.combatLog(WoWSpell.FromId(EXHILARATION).Name);
                LastSpell = EXHILARATION;

            }));
        }
        #endregion

        #region cast deterrence

        public static Composite CastDeterrence()
        {
            return
                new Decorator(ret => Me.GotTarget
                    && SpellManager.HasSpell(DETERRENCE)
                    && !U.spellOnCooldown(DETERRENCE)
                    && Me.HealthPercent <= CP.myPrefs.PercentDeterrence
                    && SpellManager.CanCast(DETERRENCE)
                    && LastSpell != DETERRENCE,
            new Action(ret =>
            {
                SpellManager.Cast(DETERRENCE);
                L.combatLog(WoWSpell.FromId(DETERRENCE).Name);
                LastSpell = DETERRENCE;

            }));
        }
        #endregion

        #region cast Counter Shot
        public static int INTERRUPT = 9999999;
        public static Composite CastCounterShot()
        {
            return
                new Decorator(ret => Me.GotTarget
                    && CP.myPrefs.AutoInterrupt
                    && SpellManager.HasSpell(COUNTER_SHOT)
                    && !U.spellOnCooldown(COUNTER_SHOT)
                    && Me.CurrentTarget.Distance <= 39
                    && (Me.CurrentTarget.IsCasting && I.ItsTimeToInterrupt)
                    && SpellManager.CanCast(COUNTER_SHOT)
                    && LastSpell != INTERRUPT,
            new Action(ret =>
            {
                SpellManager.Cast(COUNTER_SHOT);
                L.combatLog(WoWSpell.FromId(COUNTER_SHOT).Name);
                LastSpell = INTERRUPT;

            }));
        }
        #endregion

        #region cast wyvern sting
        public static Composite CastWyvernSting()
        {
            return
                new Decorator(ret => Me.GotTarget
                    && CP.myPrefs.AutoInterrupt
                    && SpellManager.HasSpell(WYVERN_STING)
                    && !U.spellOnCooldown(WYVERN_STING)
                    && Me.CurrentTarget.Distance <= 39
                    && (Me.CurrentTarget.IsCasting && I.ItsTimeToInterrupt)
                    && SpellManager.CanCast(WYVERN_STING)
                    && LastSpell != INTERRUPT,
            new Action(ret =>
            {
                SpellManager.Cast(WYVERN_STING);
                L.combatLog(WoWSpell.FromId(WYVERN_STING).Name);
                LastSpell = INTERRUPT;

            }));
        }
        #endregion

        #region cast murder of crows
        public static Composite CastMurderOfCrows()
        {
            return
                new Decorator(ret => Me.GotTarget
                    && useMyMurder
                    && SpellManager.HasSpell(MURDER_OF_CROWS)
                    && !U.spellOnCooldown(MURDER_OF_CROWS)
                    && Me.FocusPercent >= 30
                    && Me.CurrentTarget.Distance <= 39
                    && SpellManager.CanCast(MURDER_OF_CROWS)
                    && LastSpell != MURDER_OF_CROWS,
            new Action(ret =>
            {
                SpellManager.Cast(MURDER_OF_CROWS);
                L.combatLog(WoWSpell.FromId(MURDER_OF_CROWS).Name);
                LastSpell = MURDER_OF_CROWS;

            }));
        }
        #endregion

        #region black arrow
        public static Composite CastBlackArrow()
        {
            return
                new Decorator(ret => Me.GotTarget
                    && SpellManager.HasSpell(BLACK_ARROW)
                    && !U.spellOnCooldown(BLACK_ARROW)
                    && !U.debuffExists(BLACK_ARROW, Me.CurrentTarget)
                    && Me.FocusPercent >= 35
                    && Me.CurrentTarget.Distance <= 39
                    && SpellManager.CanCast(BLACK_ARROW)
                    && LastSpell != BLACK_ARROW,
            new Action(ret =>
            {
                SpellManager.Cast(BLACK_ARROW);
                L.combatLog(WoWSpell.FromId(BLACK_ARROW).Name);
                LastSpell = BLACK_ARROW;

            }));
        }
        #endregion

        #region explosive shot
        public static Composite CastExplosiveShot()
        {
            return
                new Decorator(ret => Me.GotTarget
                    && SpellManager.HasSpell(EXPLOSIVE_SHOT)
                    && !U.spellOnCooldown(EXPLOSIVE_SHOT)
                    && Me.FocusPercent >= 15
                    && Me.CurrentTarget.Distance <= 39
                    && SpellManager.CanCast(EXPLOSIVE_SHOT)
                    && LastSpell != EXPLOSIVE_SHOT,
            new Action(ret =>
            {

                SpellManager.Cast(EXPLOSIVE_SHOT);
                L.combatLog(WoWSpell.FromId(EXPLOSIVE_SHOT).Name);
                LastSpell = EXPLOSIVE_SHOT;

            }));
        }
        public static Composite CastExplosiveShotProc()
        {
            return
                new Decorator(ret => Me.GotTarget
                    && SpellManager.HasSpell(EXPLOSIVE_SHOT)
                    && Me.CurrentTarget.Distance <= 39
                    && SpellManager.CanCast(EXPLOSIVE_SHOT),
            new Action(ret =>
            {
                    SpellManager.Cast(EXPLOSIVE_SHOT);
                    L.combatLog(WoWSpell.FromId(EXPLOSIVE_SHOT).Name);
                    LastSpell = EXPLOSIVE_SHOT;
                
            }));
        }
        #endregion

        #region arcane shot
        public static Composite CastArcaneShotBM()
        {
            return
                new Decorator(ret => Me.GotTarget
                    && SpellManager.HasSpell(ARCANE_SHOT)
                    && Me.FocusPercent >= 60
                    && Me.CurrentTarget.Distance <= 39
                    && SpellManager.CanCast(ARCANE_SHOT),
            new Action(ret =>
            {
                SpellManager.Cast(ARCANE_SHOT);
                L.combatLog(WoWSpell.FromId(ARCANE_SHOT).Name);
                LastSpell = ARCANE_SHOT;

            }));
        }
        public static Composite CastArcaneShot()
        {
            return
                new Decorator(ret => Me.GotTarget
                    && SpellManager.HasSpell(ARCANE_SHOT)
                    && ((Me.FocusPercent >= 60 && U.debuffExists(SERPENT_STING, Me.CurrentTarget))
                    || (Me.FocusPercent >= 30 && !U.debuffExists(SERPENT_STING, Me.CurrentTarget)))
                    && Me.CurrentTarget.Distance <= 39
                    && SpellManager.CanCast(ARCANE_SHOT),
            new Action(ret =>
            {
                SpellManager.Cast(ARCANE_SHOT);
                L.combatLog(WoWSpell.FromId(ARCANE_SHOT).Name);
                LastSpell = ARCANE_SHOT;

            }));
        }
        #endregion

        #region concussive shot
        public static Composite CastConcussiveShot()
        {
            return
                new Decorator(ret => Me.GotTarget
                    && SpellManager.HasSpell(CONCUSSIVE_SHOT)
                    && !U.debuffExists(CONCUSSIVE_SHOT, Me.CurrentTarget)
                    && Me.CurrentTarget.Distance <= 39
                    && SpellManager.CanCast(CONCUSSIVE_SHOT)
                    && LastSpell != CONCUSSIVE_SHOT,
            new Action(ret =>
            {
                SpellManager.Cast(CONCUSSIVE_SHOT);
                L.combatLog(WoWSpell.FromId(CONCUSSIVE_SHOT).Name);
                LastSpell = CONCUSSIVE_SHOT;

            }));
        }
        #endregion

        #region Cobra shot

        public static Composite CastCobraShot()
        {
            return
                new Decorator(ret => Me.GotTarget
                    && SpellManager.HasSpell(COBRA_SHOT)
                    && Me.FocusPercent < 60
                    && Me.CurrentTarget.Distance <= 39
                    && SpellManager.CanCast(COBRA_SHOT),
            new Action(ret =>
            {
                SpellManager.Cast(COBRA_SHOT);
                L.combatLog(WoWSpell.FromId(COBRA_SHOT).Name);
                LastSpell = COBRA_SHOT;

            }));
        }
        #endregion

        #region barrage
        public static Composite CastBarrage()
        {
            return
                new Decorator(ret => Me.GotTarget
                    && SpellManager.HasSpell(BARRAGE)
                    && !U.spellOnCooldown(BARRAGE)
                    && !Me.IsChanneling
                    && Me.FocusPercent >= 60
                    && Me.CurrentTarget.Distance <= 39
                    && SpellManager.CanCast(BARRAGE)
                    && LastSpell != BARRAGE,
            new Action(ret =>
            {
                SpellManager.Cast(BARRAGE);
                L.combatLog(WoWSpell.FromId(BARRAGE).Name);
                LastSpell = BARRAGE;

            }));
        }
        #endregion

        #region powershot
        public static Composite CastPowerShot()
        {
            return
                new Decorator(ret => Me.GotTarget
                    && SpellManager.HasSpell(POWERSHOT)
                    && !U.spellOnCooldown(POWERSHOT)
                    && Me.FocusPercent >= 15
                    && Me.CurrentTarget.Distance <= 39
                    && SpellManager.CanCast(POWERSHOT)
                    && LastSpell != POWERSHOT,
            new Action(ret =>
            {
                SpellManager.Cast(POWERSHOT);
                L.combatLog(WoWSpell.FromId(POWERSHOT).Name);
                LastSpell = POWERSHOT;

            }));
        }
        #endregion

        #region glaive toss
        public static Composite CastGlaiveToss()
        {
            return
                new Decorator(ret => Me.GotTarget
                    && SpellManager.HasSpell(GLAIVE_TOSS)
                    && !U.spellOnCooldown(GLAIVE_TOSS)
                    && Me.FocusPercent >= 15
                    && Me.CurrentTarget.Distance <= 39
                    && SpellManager.CanCast(GLAIVE_TOSS)
                    && LastSpell != GLAIVE_TOSS,
            new Action(ret =>
            {
                SpellManager.Cast(GLAIVE_TOSS);
                L.combatLog(WoWSpell.FromId(GLAIVE_TOSS).Name);
                LastSpell = GLAIVE_TOSS;

            }));
        }
        #endregion

        #region dire beast
        public static Composite CastDireBeast()
        {
            return
                new Decorator(ret => Me.GotTarget
                    && SpellManager.HasSpell(DIRE_BEAST)
                    && !U.spellOnCooldown(DIRE_BEAST)
                    && Me.CurrentTarget.Distance <= 39
                    && SpellManager.CanCast(DIRE_BEAST)
                    && LastSpell != DIRE_BEAST,
            new Action(ret =>
            {
                SpellManager.Cast(DIRE_BEAST);
                L.combatLog(WoWSpell.FromId(DIRE_BEAST).Name);
                LastSpell = DIRE_BEAST;

            }));
        }
        #endregion

        #region misdirection
        public static WoWUnit misOnWho()
        {
            WoWUnit onWho = null;
            if (CP.myPrefs.Misdirection == 2) { onWho = Me.Pet; }
            if (CP.myPrefs.Misdirection == 3) { onWho = Me.FocusedUnit; }
            if (CP.myPrefs.Misdirection == 4)
            {
                var TankTarget = Tanks.FirstOrDefault();
                if (TankTarget != null) { onWho = TankTarget; }
            }
            return onWho;
        }

        public static Composite castMisdirection()
        {
            return new Decorator(ret => Me.GotTarget
                && SpellManager.HasSpell(MISDIRECTION)
                && Me.ThreatInfo.RawPercent >= 85
                && !U.buffExists(MISDIRECTION, Me)
                && SpellManager.CanCast(MISDIRECTION)
                && LastSpell != MISDIRECTION,
                new Action(ret =>
                {
                    SpellManager.Cast(MISDIRECTION, misOnWho());
                    Logging.Write(Colors.BurlyWood, "Misdirection on : " + misOnWho().SafeName);
                    LastSpell = MISDIRECTION;
                }));
        }

        #endregion

        #region tanks
        public static List<WoWPlayer> Tanks
        {
            get
            {
                if (!StyxWoW.Me.GroupInfo.IsInParty)
                    return new List<WoWPlayer>(); ;

                return StyxWoW.Me.GroupInfo.RaidMembers.Where(p => p.HasRole(WoWPartyMember.GroupRole.Tank))
                    .Select(p => p.ToPlayer()).Where(p => p != null && p.IsAlive).ToList();
            }
        }
        public static bool AnyTankNearby
        {
            get
            {
                return Tanks.Any(h => h.IsAlive && h.Distance < 40);
            }
        }
        #endregion

        #region pet
        public static DateTime nextCallAllowed;
        public static void SetNextCallAllowed()
        {
            nextCallAllowed = DateTime.Now + new TimeSpan(0, 0, 0, 0, 4000);
        }
        public static DateTime nextReviveAllowed;
        public static void SetNextReviveAllowed()
        {
            nextReviveAllowed = DateTime.Now + new TimeSpan(0, 0, 0, 0, 2000);
        }
        public static Composite CallPet()
        {
            return new Decorator(ret => CanBuff && Me.Pet == null && nextCallAllowed <= DateTime.Now,
                new Action(ret =>
            {
                string SoloPet = "Call Pet " + CP.myPrefs.PetSolo;
                string RaidPet = "Call Pet " + CP.myPrefs.PetRaid;
                string BGPet = "Call Pet " + CP.myPrefs.PetBG;
                if (!Me.CurrentMap.IsRaid
                    && !Me.CurrentMap.IsInstance
                    && !Me.CurrentMap.IsDungeon
                    && !Me.CurrentMap.IsBattleground)
                {
                    SpellManager.Cast(SoloPet);
                    L.combatLog(SoloPet);
                    SetNextReviveAllowed();
                    SetNextCallAllowed();
                    return RunStatus.Success;
                }
                else if (Me.CurrentMap.IsBattleground)
                {
                    SpellManager.Cast(BGPet);
                    L.combatLog(BGPet);
                    SetNextReviveAllowed();
                    SetNextCallAllowed();
                    return RunStatus.Success;
                }
                else if (Me.CurrentMap.IsRaid
                    && Me.CurrentMap.IsInstance
                    && Me.CurrentMap.IsDungeon
                    && !Me.CurrentMap.IsBattleground)
                {
                    SpellManager.Cast(BGPet);
                    L.combatLog(BGPet);
                    SetNextReviveAllowed();
                    SetNextCallAllowed();
                    return RunStatus.Success;
                }
                return RunStatus.Failure;
            }));
        }

        public static Composite RevivePet()
        {
            return new Decorator(ret => Me.Pet == null && nextReviveAllowed <= DateTime.Now,
                new Action(ret =>
            {
                SpellManager.Cast("Revive Pet");
                L.combatLog("Revive Pet");
            }));
        }
        public static Composite ReviveDeadPet()
        {
            return new Decorator(ret => Me.Pet != null && Me.Pet.IsDead,
                new Action(ret =>
                {
                    SpellManager.Cast("Revive Pet");
                    L.combatLog("Revive Pet");
                }));
        }
        #endregion

        #region can buff
        public static bool CanBuff
        {
            get
            {
                return !Me.Mounted && !Me.IsFlying && !Me.OnTaxi && !Me.IsDead && !Me.IsGhost && !Me.IsCasting;
            }
        }
        #endregion

        #region trinkets, gloves, racials
        public static bool useMyTrinket1
        {
            get
            {
                if (CP.myPrefs.Trinket1 == 1) { return false; }
                if (T.IsWoWBoss(Me.CurrentTarget) && CP.myPrefs.Trinket1 == 2 && !CP.myPrefs.CDTrinket1) { return true; }
                if (CP.myPrefs.Trinket1 == 2 && CP.myPrefs.CDTrinket1 && HKM.cooldownsOn) { return true; }
                if (CP.myPrefs.Trinket1 == 2 && !CP.myPrefs.CDTrinket1) { return true; }
                if (CP.myPrefs.Trinket1 == 3 && Me.HealthPercent <= CP.myPrefs.PercentTrinket1HP) { return true; }

                return false;
            }
        }
        public static bool useMyTrinket2
        {
            get
            {
                if (CP.myPrefs.Trinket2 == 1) { return false; }
                if (T.IsWoWBoss(Me.CurrentTarget) && CP.myPrefs.Trinket2 == 2 && !CP.myPrefs.CDTrinket2) { return true; }
                if (CP.myPrefs.Trinket2 == 2 && CP.myPrefs.CDTrinket2 && HKM.cooldownsOn) { return true; }
                if (CP.myPrefs.Trinket2 == 2 && !CP.myPrefs.CDTrinket2) { return true; }
                if (CP.myPrefs.Trinket2 == 3 && Me.HealthPercent <= CP.myPrefs.PercentTrinket2HP) { return true; }

                return false;
            }
        }
        public static bool useMyGloves
        {
            get
            {
                if (CP.myPrefs.Gloves == 1) { return false; }
                if (T.IsWoWBoss(Me.CurrentTarget) && CP.myPrefs.Gloves == 2 && !CP.myPrefs.CDGloves) { return true; }
                if (CP.myPrefs.Gloves == 2 && CP.myPrefs.CDGloves && HKM.cooldownsOn) { return true; }
                if (CP.myPrefs.Gloves == 2 && !CP.myPrefs.CDGloves) { return true; }

                return false;
            }
        }
        public static bool useMyBloodfury
        {
            get
            {
                if (!CP.myPrefs.Bloodfury) { return false; }
                if (T.IsWoWBoss(Me.CurrentTarget) && !CP.myPrefs.CDRacial) { return true; }
                if (CP.myPrefs.Bloodfury && CP.myPrefs.CDRacial && HKM.cooldownsOn) { return true; }
                if (CP.myPrefs.Bloodfury && !CP.myPrefs.CDRacial) { return true; }

                return false;
            }
        }
        public static bool useMyBerserking
        {
            get
            {
                if (!CP.myPrefs.Berserking) { return false; }
                if (T.IsWoWBoss(Me.CurrentTarget) && !CP.myPrefs.CDRacial) { return true; }
                if (CP.myPrefs.Berserking && CP.myPrefs.CDRacial && HKM.cooldownsOn) { return true; }
                if (CP.myPrefs.Berserking && !CP.myPrefs.CDRacial) { return true; }

                return false;
            }
        }
        public static bool useMyStampede
        {
            get
            {
                if (T.IsWoWBoss(Me.CurrentTarget) && !CP.myPrefs.CDStampede) { return true; }
                if (CP.myPrefs.CDStampede && HKM.cooldownsOn) { return true; }
                return false;
            }
        }
        public static bool useMyMurder
        {
            get
            {
                if (T.IsWoWBoss(Me.CurrentTarget) && !CP.myPrefs.CDMurder) { return true; }
                if (CP.myPrefs.CDMurder && HKM.cooldownsOn) { return true; }

                return false;
            }
        }
        #endregion
    }
}
